<template>
  <vxe-grid
    v-show="!isHidden"
    v-bind="gridOptions"
    @radio-change="radioChangeEvent"
    @checkbox-change="($event) => checkboxChangeEvent($event, 'checkbox-change')"
    @checkbox-all="($event) => checkboxChangeEvent($event, 'checkbox-all')"
    @resizable-change="resizableChangeEvent"
    @custom="customEvent"
    v-on="$listeners"
  >
    <!-- form 插槽-->
    <template v-slot:form>
      <slot name="form"></slot>
    </template>

    <!-- toolbar buttons 插槽-->
    <template v-slot:toolbar_buttons>
      <slot name="toolbar_buttons"></slot>
    </template>

    <!-- toolbar_tools 插槽-->
    <template v-slot:toolbar_tools>
      <slot name="toolbar_tools"></slot>
    </template>

    <!-- top 插槽-->
    <template v-slot:top>
      <slot name="top"></slot>
    </template>

    <!-- bottom 插槽-->
    <template v-slot:bottom>
      <slot name="bottom"></slot>
    </template>

    <!--自定义插槽 表格内容-->
    <template v-for="slot in templates" v-slot:[slot]="scope">
      <slot :name="slot" v-bind:scope="scope" />
    </template>

    <!--自定义分页 pager 插槽-->
    <template v-if="showPage || showCount" #pager>
      <vxe-pager
        :layouts="showPage ? ['Total', 'Sizes', 'PrevPage', 'Number', 'NextPage', 'FullJump'] : []"
        :current-page.sync="tablePage.currentPage"
        :page-size.sync="tablePage.pageSize"
        :total="tablePage.total"
        @page-change="handlePageChange"
      >
        <template v-if="showCount" #left>
          <span class="page-left">
            <span class="select-count" v-if="showCountDetail">{{
              $t("common.common_selected_total", { 0: selectRecords.length })
            }}</span>
            <el-button type="text" @click="clearCheck" style="margin-left: 5px">{{
              $t("common.common_clear", { 0: selectRecords.length })
            }}</el-button>
          </span>
        </template>
      </vxe-pager>
    </template>
  </vxe-grid>
</template>
<script>
import Sortable from "sortablejs";
import VXETable from "vxe-table";

export default {
  props: {
    options: {
      type: Object,
      required: true,
    },
    tablePage: {
      type: Object,
      default: () => {
        return {
          currentPage: 1,
          pageSize: 10,
          total: 0,
        };
      },
    },
    showPage: {
      type: Boolean,
      default: true,
    },
    showCount: {
      type: Boolean,
      default: true,
    },
    showCountDetail: {
      type: Boolean,
      default: true,
    },
    columnDraggable: {
      type: Boolean,
      default: true,
    },
    rowDropElement: {
      type: String,
      default: "",
    },
    columnChangeSave: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      isHidden: true,
      columnChangeSaveRecordId: null, 
      sortable1: null,
      sortable2: null,
      isAllChecked: false,
      isIndeterminate: false,
      selectRecords: [],
      defaultOptions: {
        id: "id",
        height: "650",
        rowId: "id",
        ref: "xGrid",
        headerRowClassName: "sortable-xGrid-header-row",
        headerCellClassName: "sortable-xGrid-header-cell",
        cellClassName: "sortable-xGrid-cell",
        class: "sortable-xGrid",
        border: false,
        showOverflow: "tooltip",
        rowConfig: {
          useKey: true,
          isHover: true
        },
        columnConfig: {
          useKey: true,
          resizable: true,
        },
        checkboxConfig: {
          highlight: true,
        },
        radioConfig: {
          highlight: true,
        },
        scrollX: {
          enabled: true,
        },
        toolbarConfig: {
          custom: {
            immediate: false,
            showFooter: true,
            icon: "vxe-icon-feedback",
          },
          slots: {
            buttons: "toolbar_buttons",
          },
        },
      },
    };
  },
  computed: {
    gridOptions() {
      return this.deepMerge({}, this.defaultOptions, this.options);
    },
    templates() {
      let result = [];
      this.gridOptions.columns.forEach((column) => {
        if (column.slots) {
          let slotsList = Object.values(column.slots);
          slotsList.forEach((slot) => {
            if (result.indexOf(slot) === -1) {
              result.push(slot);
            }
          });
        }
      });
      return result;
    },
  },
  created() {
    this.isHidden = this.columnChangeSave
    if (this.columnDraggable) {
      this.columnDrop();
    }
    if (this.rowDropElement) {
      this.rowDrop();
    }
  },
  mounted() {
    this.getCustomColumn();
  },
    beforeDestroy() {
    if (this.sortable1) {
      this.sortable1.destroy();
    }
    if (this.sortable2) {
      this.sortable2.destroy();
    }
  },
  methods: {
    deepMerge(target, ...sources) {
      sources.forEach(source => {
        for (const key in source) {
          if (source[key] instanceof Object && !Array.isArray(source[key]) && typeof source[key] !== 'function') {
            if (!target[key]) {
              Object.assign(target, { [key]: {} });
            }
            this.deepMerge(target[key], source[key]);
          } else {
            Object.assign(target, { [key]: source[key] });
          }
        }
      });
      return target;
    },
    seqFunction({ seq }) {
      return seq + (this.tablePage.currentPage - 1) * this.tablePage.pageSize;
    },
    checkColumnMethod({ column }) {
      return column.type !== "checkbox" && column.field !== "table_operate";
    },
    radioChangeEvent() {
      const $grid = this.$refs[this.gridOptions.ref];
      this.selectRecords = [$grid.getRadioRecord()];
      this.$emit("changeEvent", $grid.getRadioRecord());
    },
    loadData(data) {
      const $grid = this.$refs[this.gridOptions.ref];
      $grid.loadData(data);
    },
    // 单选回显
    setRadioRow(row) {
      const $grid = this.$refs[this.gridOptions.ref];
      $grid.setRadioRow(row);
    },
    clearRadioRow() {
      const $grid = this.$refs[this.gridOptions.ref];
      $grid.clearRadioRow();
    },
    // 多选回显
    setCheckboxRow(rows, check) {
      const $grid = this.$refs[this.gridOptions.ref];
      $grid.setCheckboxRow(rows, check);
    },
    checkboxChangeEvent(checked, val) {
      const $grid = this.$refs[this.gridOptions.ref];
      this.isAllChecked = $grid.isAllCheckboxChecked();
      this.isIndeterminate = $grid.isAllCheckboxIndeterminate();
      this.selectRecords = $grid.getCheckboxRecords();
      this.$emit("changeEvent", $grid.getCheckboxRecords(), checked, val);
    },
    changeAllEvent() {
      const $grid = this.$refs[this.gridOptions.ref];
      $grid.setAllCheckboxRow(this.isAllChecked);
      this.selectRecords = $grid.getCheckboxRecords();
    },
    // 生成行拖拽
    rowDrop() {
      this.$nextTick(() => {
        const $table = this.$refs[this.gridOptions.ref];
        this.sortable1 = Sortable.create($table.$el.querySelector(".body--wrapper>.vxe-table--body tbody"), {
          handle: this.rowDropElement,
          onEnd: ({ newIndex, oldIndex }) => {
            const currRow = this.options.data.splice(oldIndex, 1)[0];
            this.options.data.splice(newIndex, 0, currRow);
            this.$emit("tableRowDrop", newIndex, oldIndex);
          },
        });
      });
    },
    // 生成列拖拽
    columnDrop() {
      this.$nextTick(() => {
        const $table = this.$refs[this.gridOptions.ref];
        this.sortable2 = Sortable.create(
          $table.$el.querySelector(".body--wrapper>.vxe-table--header .vxe-header--row"),
          {
            handle: ".vxe-header--column",
            onEnd: ({ item, newIndex, oldIndex }) => {
              const { fullColumn, tableColumn } = $table.getTableColumn();
              const targetThElem = item;
              const wrapperElem = targetThElem.parentNode;
              const newColumn = fullColumn[newIndex];
              const oldColumn = fullColumn[oldIndex];
              if (oldColumn.fixed || newColumn.fixed) {
                const oldThElem = wrapperElem.children[oldIndex];
                // 错误的移动
                if (newIndex > oldIndex) {
                  wrapperElem.insertBefore(targetThElem, oldThElem);
                } else {
                  wrapperElem.insertBefore(targetThElem, oldThElem ? oldThElem.nextElementSibling : oldThElem);
                }
                VXETable.modal.message({ content: "不能拖动固定列或拖动至固定列位置", status: "error" });
                return;
              }
              // 获取列索引 columnIndex > fullColumn
              const oldColumnIndex = $table.getColumnIndex(tableColumn[oldIndex]);
              const newColumnIndex = $table.getColumnIndex(tableColumn[newIndex]);
              // 移动到目标列
              const currRow = fullColumn.splice(oldColumnIndex, 1)[0];
              fullColumn.splice(newColumnIndex, 0, currRow);
              $table.loadColumn(fullColumn);
              this.customColumnSave();
            },
          }
        );
      });
    },
    //列宽事件
    resizableChangeEvent() {
      this.customColumnSave();
    },
    //自定义事件
    customEvent({type}) {
      if (type === 'confirm') {
        this.customColumnSave();
      } else if(type === 'reset') {
        this.clearCustomColumnSave();
      }
    },

    //触发自定义列保存
    customColumnSave() {
      if (!this.columnChangeSave) {
        return;
      }
      const $table = this.$refs[this.gridOptions.ref];
      const { fullColumn } = $table.getTableColumn();
      let obj = {
        content: JSON.stringify(fullColumn),
        resource: this.$route.path,
        userId: JSON.parse(sessionStorage.getItem("user")).id,
      };
      this.$server().erdfRequest("/server/function-user/base/ResourceUser/insert", obj, "POST");
    },
    clearCustomColumnSave() {
      if (!this.columnChangeSaveRecordId) {
        return
      }
      this.$server().delete("function-user", "ResourceUser",{id:this.columnChangeSaveRecordId}, true)
          .then(() => {
            const $table = this.$refs[this.gridOptions.ref]
            $table.reloadColumn(this.gridOptions.columns);
          })
          .catch(res => {
            this.$message.error(res.data.message);
          })
    },
    //获取自定义列表保存
    getCustomColumn() {
      if (!this.columnChangeSave) {
        return;
      }
      this.$server()
        .query(
          "function-user",
          "ResourceUser",
          {
            AND: [
              ["isDelete", "=", 0],
              ["resource", "=", this.$route.path],
              ["userId", "=", JSON.parse(sessionStorage.getItem("user")).id],
            ],
          },
          null,
          { current: 1, size: 10 },
          true
        )
        .then((res) => {
          if (res.list.length > 0) {
            this.$nextTick(() => {
              const $table = this.$refs[this.gridOptions.ref]
              this.columnChangeSaveRecordId = res.list[0].id
              let columns = JSON.parse(res.list[0].content)
              columns.forEach(item => {
                if (item.resizeWidth !== 0) {
                  item.width = item.renderWidth || item.width
                }
              })
              $table.loadColumn(columns);
              this.isHidden = false
            });
          } else {
            this.isHidden = false
          }
        });
    },
    //父级使用
    getSelectRecords() {
      return this.selectRecords;
    },
    handlePageChange({ currentPage, pageSize }) {
      this.selectRecords = [];
      this.$refs[this.gridOptions.ref].clearScroll();
      //提交方法至父组件
      this.$emit("handlePageChange", { currentPage, pageSize });
    },
    clearCheck() {
      this.$refs[this.gridOptions.ref].clearCheckboxRow();
      this.selectRecords = [];
      this.$emit("clearEvent", this.selectRecords);
    },
    // 父级使用设置当前高亮行，开启rowConfig.isCurrent启用
    setCurrentRow(row) {
      this.$refs[this.gridOptions.ref].setCurrentRow(row);
    },
  },
};
</script>
<style lang="scss" scoped>
::v-deep.vxe-body--column {
  height: 36px;
}
::v-deep.sortable-xGrid .vxe-cell--checkbox.is--disabled {
  .vxe-checkbox--icon {
    color: #d1d3d84d !important;
    font-weight: 100 !important;
  }
  .vxe-icon-checkbox-checked {
    color: #436de54d !important;
  }
  .vxe-icon-checkbox-indeterminate {
    color: #436de54d !important;
  }
}
::v-deep.sortable-xGrid .vxe-cell--checkbox {
  .vxe-checkbox--icon {
    color: #d1d3d8 !important;
    font-weight: 100 !important;
  }
  .vxe-icon-checkbox-checked {
    color: #436de5 !important;
  }
  .vxe-icon-checkbox-indeterminate {
    color: #436de5 !important;
  }
}
::v-deep.sortable-xGrid .vxe-cell--radio.is--disabled {
  .vxe-radio--icon {
    color: #d1d3d84d !important;
    font-weight: 100 !important;
  }
  .vxe-icon-radio-checked {
    color: #436de54d !important;
  }
  .vxe-icon-radio-indeterminate {
    color: #436de54d !important;
  }
}
::v-deep.sortable-xGrid .vxe-cell--radio {
  .vxe-radio--icon {
    color: #d1d3d8 !important;
    font-weight: 100 !important;
  }
  .vxe-icon-radio-checked {
    color: #436de5 !important;
  }
  .vxe-icon-radio-indeterminate {
    color: #436de5 !important;
  }
}
::v-deep.sortable-xGrid .row--radio{
  background: #eef6ff;
  background-color: #eef6ff !important;
}
::v-deep.sortable-xGrid .row--hover {
  background: #f4f5f8;
}
::v-deep.sortable-xGrid .row--checked {
  background: #eef6ff;
  background-color: #eef6ff !important;
}
::v-deep.sortable-xGrid .vxe-pager {
  .vxe-pager--prev-btn {
    min-width: 2em;
    margin: 0;
    margin-left: 1.3em;
  }
  .vxe-pager--next-btn {
    min-width: 2em;
    margin: 0;
    margin-right: 1.3em;
  }
  .vxe-pager--btn-wrapper {
    .is--active {
      background: #eef6ff;
    }
    .vxe-pager--num-btn {
      min-width: 2em;
      margin: 0;
    }
    .vxe-pager--num-btn:focus {
      box-shadow: none;
    }
  }

  .vxe-pager--jump {
    .vxe-pager--goto {
      width: 3em;
    }
    .vxe-pager--goto-text {
      margin-right: 0.85em;
    }
    .vxe-pager--classifier-text {
      margin-left: 0.85em;
    }
  }
}
::v-deep.sortable-xGrid .vxe-tools--operate {
  button {
    border: 1px solid #e2e8ec;
    background: #f8f9fc;
    border-radius: 4px;
    width: 36px;
    height: 36px;
  }
  button:hover {
    background: #eef6ff;
    color: unset;
  }
  button:active {
    border: none !important;
    background: #3255e5 !important;
    color: #FFFFFF !important;
  }
  button:focus {
    border: none !important;
    background: #3255e5 !important;
    color: #FFFFFF !important;
  }
  .vxe-custom--wrapper {
    button {
      border: 1px solid #e2e8ec;
      background: #f8f9fc;
      border-radius: 4px;
      width: 36px;
      height: 36px;
    }
    button:hover {
      background: #eef6ff;
      color: unset;
    }
  }
  .is--active {
    button {
      border: none !important;
      background: #3255e5 !important;
      color: #ffffff !important;
    }
  }
}
::v-deep.sortable-xGrid .page-left {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 10;
}

::v-deep.sortable-xGrid .vxe-header--row .vxe-header--column.sortable-ghost,
.sortable-xGrid .vxe-header--row .vxe-header--column.sortable-chosen {
  background-color: #dfecfb;
}

::v-deep.sortable-xGrid .vxe-header--row .vxe-header--column.col--fixed {
  cursor: no-drop;
}

::v-deep.sortable-xGrid .sortable-xGrid-header-row {
  height: 34px;
  border-color: #808080;
}

::v-deep.sortable-xGrid .sortable-xGrid-header-cell {
  color: #4d4e50;
  font-weight: bold;
  padding: 7px 0;
  background: #f8f9fc;
  height: 40px;
}

::v-deep.sortable-xGrid .sortable-xGrid-cell {
  height: 40px;
}

/*滚动条整体部分*/
::v-deep.sortable-xGrid ::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
/*滚动条的轨道*/
::v-deep.sortable-xGrid ::-webkit-scrollbar-track {
  background-color: #ffffff;
}
/*滚动条里面的小方块，能向上向下移动*/
::v-deep.sortable-xGrid ::-webkit-scrollbar-thumb {
  background-color: #bfbfbf;
  border-radius: 5px;
  border: 1px solid #f1f1f1;
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
::v-deep.sortable-xGrid ::-webkit-scrollbar-thumb:hover {
  background-color: #a8a8a8;
}
::v-deep.sortable-xGrid ::-webkit-scrollbar-thumb:active {
  background-color: #787878;
}
/*边角，即两个滚动条的交汇处*/
::v-deep.sortable-xGrid ::-webkit-scrollbar-corner {
  background-color: #ffffff;
}

::v-deep.sortable-xGrid .vxe-body--row.sortable-ghost {
  background-color: #dfecfb;
}
::v-deep.sortable-row-demo .vxe-body--row.sortable-chosen {
  background-color: #dfecfb;
}
</style>